package com.bt.lms.ui.page.sys.utils;

import com.alibaba.fastjson.JSONObject;
import com.bt.lms.constants.SysBizTypeConstant;
import com.bt.lms.entity.Major;
import com.bt.lms.entity.Role;
import com.bt.lms.entity.StudyCen;
import com.bt.lms.entity.User;
import com.bt.lms.entity.page.Page;
import com.bt.lms.network.msg.ReqMsg;
import com.bt.lms.network.msg.RespMsg;
import com.bt.lms.ui.page.common.PageSys;
import com.bt.lms.ui.page.sys.ServerInfo;
import com.bt.lms.ui.page.sys.major.MajorTableView;
import com.bt.lms.ui.page.sys.major.PageList;
import com.bt.lms.ui.page.sys.study.StudyCenTableView;
import com.bt.lms.ui.page.sys.user.UserTableView;
import com.bt.lms.ui.vo.PageSkipInfo;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.layout.Pane;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 网络工具类
 * @author 徐大永
 */
public class NetWorkUtils {

    /**
     * 接受  (此方法不关闭客户端)
     * @param in 输入流
     * @return 结果集
     * @throws IOException 异常
     */
    public static List<byte[]> receive(InputStream in) throws IOException {

        //缓冲集(要返回的对象)
        List<byte[]> bufS = new ArrayList<>();
        //缓冲区
        byte[] buf = new byte[1024];

        while (true) {
            int read = in.read(buf);
            int available = in.available();

            if (available != 0) {
                //没读完
                byte[] b = new byte[read];
                System.arraycopy(buf, 0, b, 0, read);
                bufS.add(b);
            } else if (read < 0) {
                //没有读到新内容
                break;
            } else if (read > 0) {
                //保留读取字节
                byte[] b = new byte[read];
                System.arraycopy(buf, 0, b, 0, read);
                bufS.add(b);
            }
        }
        return bufS;
    }

    /**
     * 请求分页界面功能
     *  通过界面跳转数据入参，进行分页条件查询界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param userPage 分页模型
     */
    public static void reqUserPagingPage(PageSkipInfo pageSkipInfo, Page<User> userPage) {
        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(userPage, SysBizTypeConstant.USER_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<User> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            Pane pane = pageSkipInfo.getPane();
            Integer index = pageSkipInfo.getIndex();
            com.bt.lms.ui.page.sys.user.PageList pageList = new com.bt.lms.ui.page.sys.user.PageList(pageSkipInfo, page);
            ObservableList<Node> children = pane.getChildren();
            children.set(index, pageList);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（用户）
     *  通过界面跳转数据入参，进行分页条件查询界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param pageSys 要添加进的界面
     */
    public static void reqUserPagingPage(PageSkipInfo pageSkipInfo, PageSys pageSys) {
        //1.发送请求
        //1.1 组装消息包
        Page<User> userPage = new Page<>();
        ReqMsg reqMsg = Encode.encodeToMsg(userPage, SysBizTypeConstant.USER_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<User> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            com.bt.lms.ui.page.sys.user.PageList pageList = new com.bt.lms.ui.page.sys.user.PageList(pageSkipInfo, page);
            pageSys.getChildren().add(pageList);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能
     *  通过界面跳转数据入参，进行分页条件查询界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param userPage 分页模型
     */
    public static void reqUserPagingPage(Pane inPane, PageSkipInfo pageSkipInfo, Page<User> userPage) {
        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(userPage, SysBizTypeConstant.USER_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<User> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            UserTableView userTableView = new UserTableView(inPane, page, pageSkipInfo);
            inPane.getChildren().set(1,userTableView);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（角色）
     *  进行整个界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param rolePage 角色分页模型
     */
    public static void reqRolePagingPage(PageSkipInfo pageSkipInfo, Page<Role> rolePage){

        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(rolePage, SysBizTypeConstant.ROLE_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<Role> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            Pane pane = pageSkipInfo.getPane();
            Integer index = pageSkipInfo.getIndex();
            com.bt.lms.ui.page.sys.role.PageList pageList = new com.bt.lms.ui.page.sys.role.PageList(pageSkipInfo, page);
            ObservableList<Node> children = pane.getChildren();
            children.set(index, pageList);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（专业）
     *  进行整个界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param majorPage 角色分页模型
     */
    public static void reqMajorPagingPage(PageSkipInfo pageSkipInfo, Page<Major> majorPage){

        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(majorPage, SysBizTypeConstant.MAJOR_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<Major> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            Pane pane = pageSkipInfo.getPane();
            Integer index = pageSkipInfo.getIndex();
            PageList pageRoleList = new PageList(pageSkipInfo, page);
            ObservableList<Node> children = pane.getChildren();
            children.set(index, pageRoleList);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（专业）
     * 只跳转列表
     *
     * @param inPane         列表所在容器（默认第一位顺序）
     * @param majorPage 角色分页模型
     * @param pageSkipInfo   界面跳转信息（总界面）
     */
    public static void reqMajorPagingPage(Pane inPane, Page<Major> majorPage, PageSkipInfo pageSkipInfo){

        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(majorPage, SysBizTypeConstant.MAJOR_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<Major> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            MajorTableView majorTableView = new MajorTableView(inPane, page,pageSkipInfo);
            inPane.getChildren().set(1, majorTableView);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（学习中心）
     *  进行整个界面的跳转
     * @param pageSkipInfo 界面跳转信息
     * @param majorPage 角色分页模型
     */
    public static void reqStudyCenPagingPage(PageSkipInfo pageSkipInfo, Page<StudyCen> majorPage){

        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(majorPage, SysBizTypeConstant.STUDY_CEN_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<StudyCen> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            Pane pane = pageSkipInfo.getPane();
            Integer index = pageSkipInfo.getIndex();
            com.bt.lms.ui.page.sys.study.PageList pageList = new com.bt.lms.ui.page.sys.study.PageList(pageSkipInfo, page);
            ObservableList<Node> children = pane.getChildren();
            children.set(index, pageList);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 请求分页界面功能（学习中心）
     * 只跳转列表
     *
     * @param inPane         列表所在容器（默认第一位顺序）
     * @param majorPage 角色分页模型
     * @param pageSkipInfo   界面跳转信息（总界面）
     */
    public static void reqStudyCenPagingPage(Pane inPane, Page<StudyCen> majorPage, PageSkipInfo pageSkipInfo){

        //1.发送请求
        //1.1 组装消息包
        ReqMsg reqMsg = Encode.encodeToMsg(majorPage, SysBizTypeConstant.STUDY_CEN_PAGE_QUERY);
        byte[] reqBytes = reqMsg.toBytes();
        //1.2 组网
        Socket socket = packageNet();
        //1.3 发网，返回结果
        List<byte[]> result = sendMes(socket, reqBytes);

        //2.处理相应
        //2.1 处理结果
        byte[] respBytes = ArrayUtils.joinBytes(result);
        //2.2 转消息
        RespMsg respMsg = RespMsg.toRespMsg(respBytes);
        //2.3 比较状态
        short status = respMsg.getStatus();
        if (status == RespMsg.NETWORK_STATUS_NORMAL) {
            //正确
            //2.4 解析消息
            String data = respMsg.getData();
            Page<StudyCen> page = JSONObject.parseObject(data, Page.class);
            //2.5 处理界面   界面跳转
            StudyCenTableView majorTableView = new StudyCenTableView(inPane, page,pageSkipInfo);
            inPane.getChildren().set(1, majorTableView);
        } else {
            //为正确回应
            String hintStr = "网络卡顿，请稍候重试";
            falseWindow(hintStr);
        }
    }

    /**
     * 失败窗口
     *
     * @param hint 提示文本
     */
    private static void falseWindow(String hint) {

        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        //弹窗提示
        alert.setTitle("失败");
        alert.setHeaderText(null);
        alert.setContentText(hint);
        alert.showAndWait();

    }

    /**
     * 发网
     *  包含读取内容
     *
     * @param socket   网
     * @param reqBytes 要发送的数据
     * @return 响应字节集
     */
    private static List<byte[]> sendMes(Socket socket, byte[] reqBytes) {

        //发送
        try {
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(reqBytes);
            outputStream.flush();

            //缓冲集
            List<byte[]> bufS = new ArrayList<>();
            //缓冲区
            byte[] buf = new byte[1024];
            InputStream in = socket.getInputStream();

            while (true) {
                int read = in.read(buf);
                int available = in.available();

                if (available != 0) {
                    //没读完
                    byte[] b = new byte[read];
                    System.arraycopy(buf, 0, b, 0, read);
                    bufS.add(b);
                } else if (read < 0) {
                    //没有读到新内容
                    break;
                } else if (read > 0) {
                    //保留读取字节
                    byte[] b = new byte[read];
                    System.arraycopy(buf, 0, b, 0, read);
                    bufS.add(b);
                }
            }
            //关闭资源
            outputStream.close();
            socket.close();
            return bufS;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 组网
     *
     * @return 网
     */
    private static Socket packageNet() {

        String ip = ServerInfo.IP;
        Integer port = ServerInfo.PORT;

        try {
            return new Socket(ip, port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}
